package com.gitee.ywj1352.design.masterWorker;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * Master
 *
 * @author: yangwenjie.a
 * @date: 2021/6/22 09:50
 * @description:
 */
public class Master {
    public static final Logger LOGGER = LoggerFactory.getLogger(Master.class);
    /**
     * 创建一个ConcurrentLinkedQueue 用来盛放任务
     * ConcurrentLinkedQueue 是一个线程安全的无界线程安全队列
     * 对元素的排序遵循先进先出的原则 获取元素时返回头部元素 添加元素则为尾部
     */
    private ConcurrentLinkedQueue<Task> taskQueue;
    /**
     * 记录结果集
     */
    private ConcurrentHashMap<String, Object> resultMap;

    /**
     * 创建HashMap<K,V> 来存放Worker对象
     */
    private Map<String, Thread> workers = new HashMap<>();

    public Master(Worker worker, int workersCount) {
        taskQueue = new ConcurrentLinkedQueue<>();
        resultMap = new ConcurrentHashMap<>();

        worker.setTaskQueue(this.taskQueue);
        worker.setResultMap(this.resultMap);

        for (int i = 0; i < workersCount; i++) {
            workers.put("worker_" + i, new Thread(worker));
        }
    }

    public void submit(Task task) {
        taskQueue.add(task);
    }

    public boolean isComplete() {
        //遍历所有的worker 只要有一个没有停止 那么就代表没有结束
        for (Map.Entry<String, Thread> me : workers.entrySet()) {
            if (me.getValue().getState() != Thread.State.TERMINATED) {
                return false;
            }
        }
        return true;
    }

    public void execute() {
        for (Map.Entry<String, Thread> entry : workers.entrySet()) {
            String key = entry.getKey();
            Thread value = entry.getValue();
            //未执行的线程执行
            if (value.getState() == Thread.State.TERMINATED || value.getState() == Thread.State.NEW) {
                value.start();
            }
            LOGGER.info("开始任务 {}:{}", key, value.getName());
        }
    }

    public int getResult() {
        int result = 0;
        for (Map.Entry<String, Object> me : resultMap.entrySet()) {
            result += (Integer)me.getValue();
        }
        return result;
    }

}
